#ifndef __WIZ_DATATYPE_SCOPEDPTR_HPP__SHANHAOBO_19800429__
#define __WIZ_DATATYPE_SCOPEDPTR_HPP__SHANHAOBO_19800429__

#include "../../Base/WizBase.hpp"

namespace Wiz
{
    namespace ScopedPtr
    {
        template<class ElementT>
        class Type : public ::Wiz::Noncopyable::Type, public ::Wiz::UnspecifiedBool::Type<::Wiz::ScopedPtr::Type<ElementT>>
        {
            WIZ_DECLARE_CLASS_THIS(Type);
            ////////////////////////////////////////////////////////////////////////
            typedef ElementT              tElement;
            typedef tElement*             tElementPtr;
            typedef tElement&             tElementRef;
            ////////////////////////////////////////////////////////////////////////
        private:
            tElementPtr                              m_Ptr;
        public:
            ::Wiz::Bool::Type IsTrue() const    /// FOR ::Wiz::UnspecifiedBool::Type
            {
                return this->IsValidPtr();
            }
        public:
            explicit Type(tElementPtr EPtr = WIZ_NULLPTR): m_Ptr(EPtr)
            {
            }

            ~Type() // never throws
            {
                ::Wiz::SafeDelete(m_Ptr); 
            }

            ::Wiz::Void::Type Reset(tElementPtr EPtr = WIZ_NULLPTR)
            {
                WIZ_ASSERT(::Wiz::NotValidPtr(EPtr) || EPtr != m_Ptr);
                tThis(EPtr).Swap(*this);
            }
            tElementRef operator*() const
            {
                WIZ_ASSERT(::Wiz::IsValidPtr(m_Ptr));
                return *m_Ptr;
            }

            tElementPtr operator->() const
            {
                WIZ_ASSERT(m_Ptr != WIZ_NULLPTR);
                return m_Ptr;
            }

            tElementPtr Get() const
            {
                return m_Ptr;
            }

            ::Wiz::Bool::Type NotValid() const
            {
                return ::Wiz::NotValidPtr(m_Ptr);
            }

            ::Wiz::Bool::Type IsValid() const
            {
                return ::Wiz::IsValidPtr(m_Ptr);
            }

            ::Wiz::Void::Type Swap(tThis& rhs)
            {
                ::Wiz::Swap(m_Ptr, rhs.m_Ptr);
            }
        };
        template<class ElementT> WIZ_INLINE ::Wiz::Void::Type
            Swap(::Wiz::ScopedPtr::Type<ElementT> & Lhs, ::Wiz::ScopedPtr::Type<ElementT> & Rhs)
        {
            Lhs.Swap(Rhs);
        }
    } /// end of namespace ScopedPtr
} /// end of namespace Wiz

#endif /*__WIZ_DATATYPE_SCOPEDPTR_HPP__SHANHAOBO_19800429__*/
